package lossy;

import java.awt.image.BufferedImage;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import javax.imageio.ImageIO;

/**
 * The Class Lossy.
 */
public class Lossy2 {
//
//	/** The Constant N - size of blocks. */
//	private static final int N = 8;
//
//	/** The height of image. */
//	private static int height;
//
//	/** The width. of image */
//	private static int width;
//
//	/** The Constant FILE_TO_READ. */
//	private static String FILE_TO_READ = "testdata//dcc2//lena.bmp";
//
//	/** The Constant COMPRESSED_FILE. */
//	private final static String COMPRESSED_FILE = "testdata//dcc2//00_compressed.bmp";
//
//	/** The Constant DECOMPRESSED_FILE. */
//	private final static String DECOMPRESSED_FILE = "testdata//dcc2//00_decompressed.bmp";
//	private final static String DECOMPRESSED_FILE2 = "testdata//dcc2//01_decompressed.bmp";
//	private final static String DECOMPRESSED_FILE_BIN = DECOMPRESSED_FILE
//			+ ".bin";
//
//	private static int THRESHOLD_VALUE = 180;
//
//	//private static List<Block> blocks = divideIntoBlocks(FILE_TO_READ);
//	
//	/**
//	 * The main method: runs compression and/or decompression
//	 * 
//	 * @param args
//	 *            the arguments
//	 */
//	public static void main(String[] args) {
//		if (args.length > 0) {
//			FILE_TO_READ = args[0];
//			THRESHOLD_VALUE = Integer.parseInt(args[1]);
//		}
//		DCT dct = new DCT();
//		compress(dct);
//		decompress(dct);
//		//calculatePSNR();
//		System.out.println("exe'd");
////		compressWithZeroHandling(dct);
////		decompressWithZeroHandling(dct);
//		System.out.println("exe'd 2");
////		double[][] temp = new double[N][N];
////		for(int i = 0; i < N; i++){
////			for(int y = 0; y < N; y++){
////				temp[i][y] = (int)(Math.random()*10);
////				System.out.print(temp[i][y]+" ");
////			}
////			System.out.println();
////		}
////		temp = dct.performDCT(temp);
////		temp = dct.performIDCT(temp);
////		for(int i = 0; i < N; i++){
////			for(int y = 0; y < N; y++){
////				System.out.print(temp[i][y]+" ");
////			}
////			System.out.println();
////		}
//	}
//
//	/**
//	 * Compression method: 
//	 * - divides image into blocks 8x8 
//	 * - performs DCT
//	 * - performs Treshold 
//	 * - TODO: compute zero effectively 
//	 * - saves file
//	 * 
//	 * @param dct
//	 */
//	public static void compress(DCT dct) {
//
//		List<Block> blocks = divideIntoBlocks(FILE_TO_READ);
//		for(int i = 0; i < N; i++){
//			for(int y = 0; y < N; y++){
//				System.out.print(blocks.get(0).getBlock()[i][y]+" ");
//			}
//			System.out.println();
//		}
//		for (Block block : blocks) {
//			double[][] out = block.getBlock();
//			out = dct.performDCT(block.getBlock());
////			out = Treshold.performTreshold(out, N, THRESHOLD_VALUE);
//			out = Threshold.performDiffTreshold(out, N, MIN_THRESHOLD_VALUE,MAX_THRESHOLD_VALUE);
////			out = LPFilter.performLowPassFilter(out, N);
//			block.setBlock(out);
//			
//		}
//		blockss = blocks;
//		saveFile(blocks, COMPRESSED_FILE, "bmp");
//		//saveFile2(blocks, DECOMPRESSED_FILE_BIN);
//	}
//
//	public static void compressWithZeroHandling(DCT dct) {
//
//		List<Block> blocks = divideIntoBlocks(FILE_TO_READ);
//		for(int i = 0; i < N; i++){
//			for(int y = 0; y < N; y++){
//				System.out.print(blocks.get(0).getBlock()[i][y]+" ");
//			}
//			System.out.println();
//		}
//		for (Block block : blocks) {
//			double[][] out = block.getBlock();
//			out = dct.performDCT(block.getBlock());
//			out = Threshold.performTreshold(out, N, THRESHOLD_VALUE);
////			out = Treshold.performDiffTreshold(out, N, MIN_THRESHOLD_VALUE,MAX_THRESHOLD_VALUE);
////			out = LPFilter.performLowPassFilter(out, N);
////                        out = LowPassFilter.performLowPassFilter(out, N);
//			out = ZeroHandler.encode(out);
//			block.setBlock(out);
//			
//		}
//		blockss = blocks;
////		saveFile(blocks, COMPRESSED_FILE, "bmp");
//		//saveFile2(blocks, DECOMPRESSED_FILE_BIN);
//	}
//	
//	private static List<Block> blockss;
//	private static final int MIN_THRESHOLD_VALUE = 8;
//	private static final int MAX_THRESHOLD_VALUE = 291;
//	/**
//	 * Decompression method: 
//	 * - divides image into blocks 8x8 
//	 * - performs iDCT -
//	 * - TODO zero effectivity? 
//	 * - saves file
//	 * 
//	 * @param dct
//	 */
//	public static void decompress(DCT dct) {
//
//		List<Block> blocks = divideIntoBlocks(COMPRESSED_FILE);
//		blocks = blockss;
//				
//		//List<Block> blocks = readFile2(DECOMPRESSED_FILE_BIN);
//		for (Block block : blocks) {
//			double[][] out = block.getBlock();
//			out = dct.performIDCT(block.getBlock());
//			block.setBlock(out);
//
//		}
//		for(int i = 0; i < N; i++){
//			for(int y = 0; y < N; y++){
//				System.out.print(blocks.get(0).getBlock()[i][y]+" ");
//			}
//			System.out.println();
//		}
//		saveFile(blocks, DECOMPRESSED_FILE, "bmp");
//
//	}
//
//	public static void decompressWithZeroHandling(DCT dct) {
//
////		List<Block> blocks = divideIntoBlocks(COMPRESSED_FILE);
////		blocks = blockss;
//		List<Block> blocks = blockss;
//		
//		double[][] bl;
//		int index = 0;
//		double[][] finalImage = new double[height][width];
//		for (int i = 0; i < width; i += N) {
//			for (int j = 0; j < height; j += N) {
//				bl = blocks.get(index).getBlock();
//				for (int ii = 0; ii < bl.length; ii++) {
//					for (int jj = 0; jj < bl[ii].length; jj++) {
//						finalImage[i + ii][j + jj] =  bl[ii][jj];
//					}
//				}
//				index++;
//			}
//		}
//		System.out.println("start trim");
//		finalImage = ZeroHandler.trimZeros(finalImage, height);
//		System.out.println("stop trim");
//		finalImage = ZeroHandler.decode(finalImage, width);
//		System.out.println("stop decode");
//		blocks.clear();
//		for (int i = 0; i < finalImage.length; i += N) {
//			for (int j = 0; j < finalImage[i].length; j += N) {
//
//				int b = 0;
//				int a;
//				double[][] blck = new double[N][N];
//				for (int ii = i; ii < (i + N); ii++) {
//					a = 0;
//					for (int jj = j; jj < (j + N); jj++) {
//						blck[b][a] = finalImage[ii][jj];
//						a++;
//					}
//					b++;
//				}
//				blocks.add(new Block(blck));
//			}
//		}
//		
//		//List<Block> blocks = readFile2(DECOMPRESSED_FILE_BIN);
//		for (Block block : blocks) {
//			double[][] out = block.getBlock();
//			out = dct.performIDCT(block.getBlock());
//			block.setBlock(out);
//
//		}
//		for(int i = 0; i < N; i++){
//			for(int y = 0; y < N; y++){
//				System.out.print(blocks.get(0).getBlock()[i][y]+" ");
//			}
//			System.out.println();
//		}
//		saveFile(blocks, DECOMPRESSED_FILE2, "bmp");
//
//	}
//	
//	private static void calculatePSNR() {
//		try {
//			FileInputStream in = new FileInputStream(FILE_TO_READ);
//			FileInputStream out = new FileInputStream(DECOMPRESSED_FILE);
//
//			long size = 0;
//			int a = 0;
//			int b = 0;
//			int maxa = 0;
//			double mse = 0;
//			while (((a = in.read()) != -1) && ((b = out.read()) != -1)) {
//				size++;
//				if (a > maxa) {
//					maxa = a;
//				}
//				mse += Math.pow((a - b), 2);
//			}
//			System.out.println("MSE: " + mse);
//			mse = mse / (double) size;
//			System.out.println("MSE: " + mse);
//			double psnr = 20 * Math.log10(((double) maxa / (double) Math
//					.sqrt(mse)));
//			System.out.println("PSNR: " + psnr);
//		} catch (Exception e) {
//			System.out.println("Error: " + e.getMessage());
//		}
//	}
//
//	/**
//	 * Divide into 8x8 blocks.
//	 * 
//	 * @param filename
//	 *            the filename
//	 * @return the list
//	 */
//	public static List<Block> divideIntoBlocks(String filename) {
//		List<Block> blocks = new ArrayList<Block>();
//		double[][] block;
//		int a = 0;
//		int b = 0;
//
//		try {
//			BufferedImage image = ImageIO.read(new FileInputStream(filename));
//			height = image.getHeight();
//			width = image.getWidth();
//
//			for (int i = 0; i < image.getWidth(); i += N) {
//				for (int j = 0; j < image.getHeight(); j += N) {
//
//					b = 0;
//					block = new double[N][N];
//					for (int ii = i; ii < (i + N); ii++) {
//						a = 0;
//						for (int jj = j; jj < (j + N); jj++) {
//							block[b][a] = image.getRGB(ii, jj);
//							a++;
//						}
//						b++;
//					}
//					blocks.add(new Block(block));
//				}
//			}
//
//		} catch (Exception e) {
//			System.out.println("error during IO - " + e.toString());
//		}
//		return blocks;
//	}
//
//	/**
//	 * Saves file.
//	 * 
//	 * @param blocks
//	 *            the blocks
//	 * @param filename
//	 *            the filename
//	 */
//	private static void saveFile(List<Block> blocks, String filename, String extension) {
//		try {
//			BufferedImage image = new BufferedImage(width, height,
//					BufferedImage.TYPE_BYTE_GRAY);
//			double[][] block;
//			int index = 0;
//
//			for (int i = 0; i < image.getWidth(); i += N) {
//				for (int j = 0; j < image.getHeight(); j += N) {
//
//					block = blocks.get(index).getBlock();
//					for (int ii = 0; ii < block.length; ii++) {
//						for (int jj = 0; jj < block[ii].length; jj++) {
//                                                    int res = (int) block[ii][jj];
//                                                    if(DCT.getRed(res) > 255){
//                                                        System.out.println(res + " "+DCT.getRed(res));
//                                                        res = DCT.mixColor(255,255,255);
//                                                    } else if(DCT.getRed(res) < 0){
//                                                        System.out.println(res + " "+DCT.getRed(res));
//                                                        res = DCT.mixColor(0,0,0);
//                                                    }
//							image.setRGB(i + ii, j + jj, res);
//						}
//					}
//					index++;
//				}
//			}
//
//			ImageIO.write(image, extension, new FileOutputStream(filename));
//
//		} catch (FileNotFoundException e) {
//			// TODO Auto-generated catch block
//			e.printStackTrace();
//		} catch (IOException e) {
//			// TODO Auto-generated catch block
//			e.printStackTrace();
//		}
//
//	}
//
//	private static void saveFile2(List<Block> blocks, String filename) {
//
//		try {
//			ObjectOutputStream oos = new ObjectOutputStream(
//					new FileOutputStream(filename));
//			oos.writeObject(blocks);
//			oos.close();
//		} catch (IOException e) {
//			// TODO Auto-generated catch block
//			e.printStackTrace();
//		}
//	}
//
//	private static List<Block> readFile2(String filename) {
//		try {
//			ObjectInputStream ois = new ObjectInputStream(new FileInputStream(
//					filename));
//			return (List<Block>) ois.readObject();
//		} catch (FileNotFoundException e) {
//			// TODO Auto-generated catch block
//			e.printStackTrace();
//		} catch (IOException e) {
//			// TODO Auto-generated catch block
//			e.printStackTrace();
//		} catch (ClassNotFoundException e) {
//			// TODO Auto-generated catch block
//			e.printStackTrace();
//		}
//		return null;
//	}
//
//	/**
//	 * Prepares a string to present 2D array.
//	 * 
//	 * @param array
//	 *            the 2D array
//	 * @return the string presenting 2D array
//	 */
//	private static String show2Darray(double[][] array) {
//		String s = "";
//		int itr = 1;
//		for (double[] dbl : array) {
//			s += itr + "->" + Arrays.toString(dbl) + ",\t";
//			itr++;
//		}
//		return s;
//	}

}
